import pytest
from datetime import datetime, timezone, timedelta

import requests
from numpy.core.defchararray import lower

from utils.request_util import Request, host
from utils.logger_util import logger
from utils.yaml_util import read_yaml, write_yaml

# pytest_plugins 已移动到顶级 conftest.py 中（Pytest 8要求）
log=logger.getlog()


@pytest.fixture(scope="module")
def lottery_schema():
    """抽奖接口响应schema验证"""
    yield {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "properties": {
            "code": {
                "type": "integer"
            },
            "data": {
                "type": "boolean"
            },
            "msg": {
                "type": "string"
            }
        },
        "additionalProperties": False,
        "required": [
            "code",
            "data",
            "msg"
        ]
    }


@pytest.fixture(scope="module")
def lottery_negative_schema():
    """抽奖接口异常响应schema验证"""
    yield {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "properties": {
            "code": {
                "type": "integer"
            },
            "data": {
                "type": ["boolean", "null"]
            },
            "msg": {
                "type": "string"
            }
        },
        "additionalProperties": False,
        "required": [
            "code",
            "data",
            "msg"
        ]
    }

@pytest.fixture(scope="function")
def no_token_headers():
    """无效的请求头（无token）"""
    return {
        'Content-Type': 'application/json'
    }

@pytest.fixture(scope="function")
def invalid_token_headers():
    """无效token的请求头"""
    return {
        'Content-Type': 'application/json',
        'user_token': 'invalid_token_123'
    }

@pytest.fixture(scope="function")
def build_negative_request_data():
    """构建异常测试请求数据的工厂函数"""
    def _build_data(test_config, activity_info,activity_create_time):
        from datetime import datetime, timezone, timedelta
        


        #创建请求体
        data = {
        }
        hour=activity_info["duration"]

        #给定当前抽奖时间
        if 'winningTime' in test_config and lower(test_config['winningTime'])=='now':
            # 获取当前时间
            current_time = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "+0000"
            data['winningTime'] = current_time

        #过期抽奖时间
        elif 'winningTime' in test_config and lower(test_config['winningTime'])=='out':
            # 计算活动过期时间（创建时间 + 持续时间）
            expiry_time = activity_create_time + timedelta(hours=hour)
            # 获取大于过期时间一小时的时间
            after_expiry_time = expiry_time + timedelta(hours=1)
            formatted_time = after_expiry_time.strftime("%Y-%m-%dT%H:%M:%S.000+0000")
            data['winningTime']=formatted_time



        #抽奖时间早于活动创建时间
        elif 'winningTime' in test_config and lower(test_config['winningTime'])=='before':
            # 获取早于活动创建一小时的时间
            before_create_time = activity_create_time - timedelta(hours=1)
            formatted_time=before_create_time.strftime("%Y-%m-%dT%H:%M:%S.000+0000")
            data['winningTime'] = formatted_time
        else: #no
            pass


        # 处理活动ID
        #返回有效的活动id
        if 'activity_id' in test_config and test_config['activity_id']==True:
            data['activityId'] = activity_info['activityId']
        #返回空
        elif 'activity_id' in test_config and test_config['activity_id'] is None:
            data['activityId'] =None
        #返回无效的activityid(在配置中提供了)
        elif 'activity_id' in test_config and test_config['activity_id'] !='no':
            data['activityId']=test_config['activity_id']
        else: #没有这个字段，就不填写
            pass
        
        # 处理奖品ID
        #有效的奖品id
        if 'prizeId' in test_config and test_config['prizeId'] ==True:
            data['prizeId'] = activity_info['activityPrizeList'][test_config['prize_index']]['prizeId']
        #无效的奖品id
        elif 'prizeId' in test_config and test_config['prizeId'] is None:
            data['prizeId']=None
        # 无效的奖品id（配置提供）
        elif 'prizeId' in test_config and test_config['prizeId']!='no':
            data['prizeId']=test_config['prizeId']
        else: #没有这个字段no
            pass

        #有效的用户id
        if 'winnerList' in test_config and test_config['winnerList']==True:
            winner_list_index=test_config['winner_list_index']
            winnerList=[]
            for i in winner_list_index:
                winnerList.append({
                    'userId': activity_info['activityUserList'][i]['userId'],
                    'userName': activity_info['activityUserList'][i]['userName'],
                })
            data['winnerList']=winnerList
        #用户列表为空
        elif 'winnerList' in test_config and test_config['winnerList'] is None:
            data['winnerList']=None
        #用户列表通过配置获取
        elif 'winnerList' in test_config and test_config['winnerList']!='no' and isinstance(test_config['winnerList']['keys'],list) and isinstance(test_config['winnerList']['values'],list) and isinstance(test_config['winnerList']['index'],list):
            #先拟定好正确场景
            winner_list_index = test_config['winner_list_index']
            winnerList = []
            for i in winner_list_index:
                winnerList.append({
                    'userId': activity_info['activityUserList'][i]['userId'],
                    'userName': activity_info['activityUserList'][i]['userName'],
                })
            data['winnerList'] = winnerList
            #覆盖错误用例
            for key, value, index in zip(test_config['winnerList']['keys'],
                                         test_config['winnerList']['values'],
                                         test_config['winnerList']['index']):
                winnerList[index][key] = value

            #最后赋值
            data['winnerList']=winnerList
        else:
            pass



        
        return data
    
    return _build_data

@pytest.fixture(scope="function")
def current_time():
    """当前时间（ISO格式）"""
    return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "+0000"

@pytest.fixture(scope="function")
def draw_prize_request_data(current_time):
    """抽奖请求基础数据模板"""
    return {
        "activityId": None,  # 需要在测试中动态设置
        "prizeId": None,     # 需要在测试中动态设置
        "winningTime": current_time,
        "winnerList": []     # 需要在测试中动态设置
    }



@pytest.fixture(scope="function")
def headers_with_token(get_token):
    """带token的请求头"""
    return {
        'Content-Type': 'application/json',
        'user_token': get_token,
    }


@pytest.fixture(scope='function')
def prepare_data(create_activity_list):
    activity_list=create_activity_list
    yield activity_list


@pytest.fixture(scope='function')
def get_activity_detail(get_activity_detail_info):
    yield get_activity_detail_info





def _build_body(activity_data,prizes,users):
    prize_list=[]
    user_list=[]
    prize_tiers = ["FIRST_PRIZE", "SECOND_PRIZE", "THIRD_PRIZE"]
    for i,prize_conf in enumerate(activity_data.get('prizes',[1])):
        if i<len(prizes):
            prize_list.append({
                'prizeId': prizes[i]['prize_id'],
                'prizeAmount': prize_conf.get('amount', 1),
                'prizeTiers': prize_tiers[i%3]
            })

    for i , user_index in enumerate(activity_data.get('user_indices',[1,2,3])):
        if user_index<len(users):
            user_list.append({
                'userId': users[user_index]['user_id'],
                'userName': users[user_index]['user_info']['name']
            })
    return {
        'activityName': activity_data['name'],
        'description': activity_data['description'],
        'duration': activity_data['duration'],
        'activityPrizeList': prize_list,
        'activityUserList': user_list
    }


def _send_create_request(url,token, body):
    """发送创建活动请求"""
    headers = {
        'Content-Type': 'application/json',
        'user_token': token
    }

    log.info(f"发送创建活动请求: {url}")
    log.info(f"请求体: {body}")

    response = requests.post(url, json=body, headers=headers)

    log.info(f"响应状态码: {response.status_code}")
    log.info(f"响应内容: {response.text}")

    return response

# 新增一个别名夹具，在本目录复用 create_six_price
@pytest.fixture(scope='function')
def create_activity_list(create_three_prizes, register_seven_users,get_token):
    """四个活动 - 从YAML配置文件读取活动数据"""
    # 使用yaml_util读取活动配置数据
    activity_data = read_yaml('lottery_prepare_data.yaml', 'activities')
    create_activity_url=host+'activity/create'
    activity_list = []
    cnt=1
    for prize_info in activity_data:
        body= _build_body(prize_info,create_three_prizes,register_seven_users)
        r=_send_create_request(create_activity_url,get_token, body)
        assert r.json()['data'] is not None,'创建活动后，返回的data不能为空'
        assert isinstance(r.json()['data']['activityId'], int), '没有返回有效的活动id'
        assert r.json()['code'] == 200 or r.json()['code'] == 0,'创建活动失败'
        body['activityId'] = r.json()['data']['activityId']
        activity_list.append(body)
        log.info(f'创建的第{cnt}个活动，活动信息：{body}')
        cnt+=1


    activity_list
    # activity_list.reverse()
    yield activity_list

@pytest.fixture(scope='function')
def check_winners_is_out(db_util):
    """
    检查中奖用户集合是否已经参与抽奖的夹具
    """
    def check_function(activity_id,winner_list):
        """
        检查指定活动中中奖用户的参与状态
        
        Args:
            activity_id: 活动ID
            
        Returns:
            int: 状态不为'INIT'的用户数量
        """
        try:
            winner_ids = []
            for winner in winner_list:
                winner_ids.append(winner['userId'])
            
            if not winner_ids:
                log.info("中奖用户列表为空，返回0")
                return 0
            
            # 将用户ID列表转换为SQL IN子句格式
            winner_ids_str = ','.join(str(uid) for uid in winner_ids)
            
            sql = f"""
                SELECT COUNT(*) as count
                FROM activity_user 
                WHERE activity_id = :activity_id 
                AND user_id IN ({winner_ids_str})
                AND status <> 'INIT'
            """
            
            log.info(f"查询活动 {activity_id} 中用户 {winner_ids} 的参与状态")
            log.info(f"执行SQL: {sql}")
            
            result = db_util.execute_query(sql, {"activity_id": activity_id})
            
            count = result[0]['count'] if result else 0
            log.info(f"状态不为'INIT'的用户数量: {count}")
            print(f"当前活动总用户数量：{len(winner_ids)}"
                  f"实际已经抽完奖品的用户数量{count}")
            return count==len(winner_ids)
            
        except Exception as e:
            log.error(f"检查中奖用户参与状态失败: {str(e)}")
            raise
    
    return check_function


@pytest.fixture(scope='function')
def check_prize_is_out(db_util):
    """检查奖品是否已经状态扭转"""
    def check_function(activity_id,prize_id):
        sql = """
            SELECT status FROM activity_prize WHERE activity_id=:activity_id
                AND prize_id=:prize_id
            """
        result = db_util.execute_query(sql, {"activity_id": activity_id, "prize_id": prize_id})

        if result:
            return result[0]['status'] == 'COMPLETED'
        return False
    return check_function

@pytest.fixture(scope='function')
def check_prize_is_full_out(db_util):
    """检查活动中所有奖品是否已经扭转"""
    def check_function(activity_id):
        sql = """
        SELECT count(*) as all_cnt, SUM(IF(status = 'COMPLETED',1,0)) as out_cnt 
        FROM activity_prize WHERE activity_id=:activity_id
        """
        result = db_util.execute_query(sql, {"activity_id": activity_id})
        if result:
            return result[0]['all_cnt'] == result[0]['out_cnt']
        return False
    return check_function

@pytest.fixture(scope='function')
def check_activity_complete(db_util):
    """检查活动是否已经结束"""
    def check_function(activity_id):
        sql="""
        SELECT status FROM activity WHERE id=:activity_id
        """
        result=db_util.execute_query(sql, {"activity_id": activity_id})
        if result:
            return result[0]['status'] == 'COMPLETED'
        else:
            return False
    return check_function


@pytest.fixture(scope='function')
def get_create_activity_time(db_util):
    def fun(activity_id):
        sql="""
        SELECT gmt_create as time FROM activity WHERE id=:activity_id 
        """
        result=db_util.execute_query(sql, {"activity_id": activity_id})
        return result[0]['time']
    return fun


@pytest.fixture(scope='function')
def get_activity_full_status(db_util):
    """
    查询活动的完整状态信息，包括活动状态、奖品信息和用户信息
    """
    def query_function(activity_id):
        """
        查询指定活动的完整状态信息
        
        Args:
            activity_id: 活动ID
            
        Returns:
            dict: 包含活动状态、奖品信息和用户信息的字典
            {
                'activity_status': str,  # 活动状态
                'prizes': [              # 奖品列表
                    {
                        'prize_id': int,
                        'status': str,
                        'prize_amount': int,
                        'prize_tiers': str
                    }
                ],
                'users': [               # 用户列表
                    {
                        'user_id': int,
                        'user_name': str,
                        'status': str
                    }
                ]
            }
        """
        try:
            result = {
                'activity_status': None,
                'prizes': [],
                'users': []
            }
            
            # 查询活动状态
            activity_sql = """
                SELECT status FROM activity WHERE id = :activity_id
            """
            activity_result = db_util.execute_query(activity_sql, {"activity_id": activity_id})
            if activity_result:
                result['activity_status'] = activity_result[0]['status']
                log.info(f"活动 {activity_id} 状态: {result['activity_status']}")
            else:
                log.warning(f"未找到活动 {activity_id}")
                return result
            
            # 查询奖品信息
            prize_sql = """
                SELECT prize_id, status, prize_amount, prize_tiers 
                FROM activity_prize 
                WHERE activity_id = :activity_id
                ORDER BY prize_id
            """
            prize_results = db_util.execute_query(prize_sql, {"activity_id": activity_id})
            for prize in prize_results:
                result['prizes'].append({
                    'prize_id': prize['prize_id'],
                    'status': prize['status'],
                    'prize_amount': prize['prize_amount'],
                    'prize_tiers': prize['prize_tiers']
                })
            log.info(f"活动 {activity_id} 奖品数量: {len(result['prizes'])}")
            
            # 查询用户信息
            user_sql = """
                SELECT user_id, user_name, status 
                FROM activity_user 
                WHERE activity_id = :activity_id
                ORDER BY user_id
            """
            user_results = db_util.execute_query(user_sql, {"activity_id": activity_id})
            for user in user_results:
                result['users'].append({
                    'user_id': user['user_id'],
                    'user_name': user['user_name'],
                    'status': user['status']
                })
            log.info(f"活动 {activity_id} 用户数量: {len(result['users'])}")
            
            return result
            
        except Exception as e:
            log.error(f"查询活动 {activity_id} 完整状态失败: {str(e)}")
            raise
    
    return query_function

